package com.michaellou.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.zip.GZIPInputStream;  
import java.util.zip.GZIPOutputStream; 

/**
 * 压缩实现类 <br>
 * 主要实现:  <br>
 *     <p>压缩单个文件、
 *     <p>压缩文件夹下的所有文件及子文件夹
 *  
 */

public class ZipTool {

    /**
     * 压缩单个文件
     * @param filePath    文件路径
     * @param fileName    文件名字
     * @param objDir      压缩文件目标文件夹
     * @param ojbZipName  压缩文件名字
     * @return
     * @throws IOException
     */
    public boolean zip(String filePath, String fileName, String objDir,
            String ojbZipName) throws IOException {
        boolean tag = false;
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(objDir
                + ojbZipName));

        FileInputStream fis = new FileInputStream(filePath + fileName);
        byte[] b = new byte[4096];
        int i = 0;

        zos.putNextEntry(new ZipEntry(fileName));
        while ((i = (fis.read(b))) > 0) {
            zos.write(b, 0, i);
        }

        fis.close();
        zos.close();

        return tag;
    }
    
    /**
     * 压缩一个文件夹下的所有文件  注意中间路径连接用"/"  如：c:/tt/ttt
     * @param srcPath     要压缩的文件夹路径
     * @param objZipPath  目标文件夹路径
     * @param ojbZipName  目标压缩文件名字
     * @return
     */
    public boolean zipDir(String srcPath, String objZipPath, String ojbZipName){

        ZipOutputStream zos = null;
        try {
            File objFile = new File(objZipPath , ojbZipName);
            zos = new ZipOutputStream(new FileOutputStream(objFile));

            if (srcPath == null) {
                System.out.println("传入的源文件夹路径字符串不能为空！");
                throw new java.lang.NullPointerException();
            }
            String dirName = "";
            File file = new File(srcPath);
            if (!file.isDirectory()) {
                throw new Exception("传入了不正确的源文件夹路径！");
            } else {
                dirName = srcPath.substring(srcPath.lastIndexOf("/") + 1);
                if (dirName == null || "".equals(dirName)) {
                    String subStr = srcPath.substring(0, srcPath.length() - 2);
                    dirName = subStr.substring(subStr.lastIndexOf("/") + 1);
                }
                ZipEntry ze = new ZipEntry(dirName + "/");
                zos.putNextEntry(ze);
                if (dirName == null || "".equals(dirName)) {
                    throw new Exception("传入了不正确的源文件夹路径！");
                }
            }

            File[] files = file.listFiles();

            for (int i = 0; i < files.length; i++) {
                zipFile(dirName + "/", files[i], zos);
            }
            return true;
        } catch (Exception e) {
            System.out.println("压缩文件时出现异常！");
            e.printStackTrace();
            return false;
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }        

    }

    /**
     * 用来压缩文件夹下的所有子文件
     * 此方法为一个递归调法方法
     * @param zipPath 要压缩的文件在压缩包中的相对路径
     * @param file    　要压缩的文件引用
     * @param zos　　 压缩文件输出流
     * @throws IOException
     */
    private void zipFile(String zipPath, File file, ZipOutputStream zos)
            throws IOException {
        //是文件夹的操作
        if (file.isDirectory()) {
            ZipEntry ze = new ZipEntry(zipPath + file.getName() + "/");
            zos.putNextEntry(ze);
            //递归调用
            for (int i = 0; i < file.listFiles().length; i++) {
                zipFile(zipPath + file.getName() + "/", file.listFiles()[i], zos);
            }
        //是文件时的操作
        }else{
            FileInputStream fis = null;            
            try{
                fis = new FileInputStream(file);
                ZipEntry ze = new ZipEntry(zipPath + file.getName());
                zos.putNextEntry(ze);
                byte []b = new byte[4096]; 
                int i = 0;
                while(  ( i = (fis.read(b)) )  >  0  ){
                    zos.write(b, 0, i);
                }
            }finally{
                if(fis != null){
                    fis.close();
                }
            }
        }
    }



    public static void main(String[] args) {
        ZipTool zt = new ZipTool();
        try {
            zt.zipDir("c:/gif", "c:/", "test.zip");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

 
  
class Test {  
  
  
    public static void main(String[] args) {  
        readFileAndWriteGZip();  
        unZipFile();  
          
    }  
  
    public static void readFileAndWriteGZip() {  
        try {  
            //打开需压缩文件作为文件输入流   
            FileInputStream fin = new FileInputStream("d:/test.txt");   
            //建立压缩文件输出流   
            FileOutputStream fout = new FileOutputStream("d:/test2.gzip");   
            //建立gzip压缩输出流    
            GZIPOutputStream gzout = new GZIPOutputStream(fout);   
            //设定读入缓冲区尺寸   
            byte[] buf = new byte[1024];  
            int num;   
            while ((num = fin.read(buf)) != -1)   
            {   
                gzout.write(buf,0,num);   
            }   
  
            gzout.close();  
            fout.close();   
            fin.close();   
            } catch (Exception ex) {  
                System.err.println(ex.toString());  
            }  
    }  
  
    public static void unZipFile() {  
  
        try {  
            //建立grip压缩文件输入流   
            FileInputStream fin = new FileInputStream("d:/test2.gzip");   
            //建立gzip解压工作流   
            GZIPInputStream gzin = new GZIPInputStream(fin);   
            //建立解压文件输出流   
            FileOutputStream fout = new FileOutputStream("d:/test2.txt");   
            byte[] buf=new byte[1024];   
            int num;   
            while ((num = gzin.read(buf,0,buf.length)) != -1)  
            {   
                fout.write(buf,0,num);   
            }   
              
            gzin.close();   
            fout.close();   
            fin.close();   
        } catch (Exception ex){  
            System.err.println(ex.toString());  
        }  
    }  
  
  
  
}  